//package com.hmdp.service.impl;
//
//import cn.hutool.core.bean.BeanUtil;
//import com.hmdp.dto.Result;
//import com.hmdp.entity.SeckillVoucher;
//import com.hmdp.entity.VoucherOrder;
//import com.hmdp.mapper.VoucherOrderMapper;
//import com.hmdp.service.ISeckillVoucherService;
//import com.hmdp.service.IVoucherOrderService;
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.hmdp.utils.RedisIdWorker;
//import com.hmdp.utils.UserHolder;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
//import org.redisson.api.stream.StreamReadParams;
//import org.springframework.aop.framework.AopContext;
//import org.springframework.beans.BeanUtils;
//import org.springframework.core.io.ClassPathResource;
//import org.springframework.data.redis.connection.stream.*;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.data.redis.core.script.DefaultRedisScript;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import javax.annotation.PostConstruct;
//import javax.annotation.Resource;
//import java.time.Duration;
//import java.time.LocalDateTime;
//import java.util.Collections;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.ArrayBlockingQueue;
//import java.util.concurrent.BlockingQueue;
//import java.util.concurrent.ExecutorService;
//import java.util.concurrent.Executors;
//
///**
// * <p>
// * 旧版
// * </p>
// *
// * @author 虎哥
// * @since 2021-12-22
// */
////@Service
//public class VoucherOrderServiceImpl1 extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
//
//    @Resource
//    private ISeckillVoucherService iSeckillVoucherService;
//    @Resource
//    private IVoucherOrderService iVoucherOrderService;
//    @Resource
//    private RedissonClient redissonClient;
//
//    @Resource
//    private RedisIdWorker redisIdWorker;
//
//    @Resource
//    private StringRedisTemplate stringRedisTemplate;
//
//    private static final DefaultRedisScript<Long> SECKILL_SCRRPT;
//
//    static {
//        SECKILL_SCRRPT = new DefaultRedisScript<>();
//        SECKILL_SCRRPT.setLocation(new ClassPathResource("Seckill.lua"));
//        SECKILL_SCRRPT.setResultType(Long.class);
//    }
//
//    // 阻塞队列
////    private BlockingQueue<VoucherOrder> orderTasks = new ArrayBlockingQueue<VoucherOrder>(1024*1024);
//    private static final ExecutorService SECKILL_ORDER_EXECUTOR = Executors.newSingleThreadExecutor();
//
//    @PostConstruct
//    private void init(){
//        SECKILL_ORDER_EXECUTOR.submit(new VoucherOrderHandler());
//    }
//
//
//    private static final String queueName = "stream.orders";
//    private class VoucherOrderHandler implements Runnable{
//        @Override
//        public void run() {
//            while (true){
//                try {
//                    // 从消息队列中读取信息
//                    List<MapRecord<String, Object, Object>> list = stringRedisTemplate.opsForStream().read(
//                            Consumer.from("g1", "c1"),
//                            StreamReadOptions.empty().count(1).block(Duration.ofSeconds(2)),
//                            StreamOffset.create(queueName, ReadOffset.lastConsumed())
//                    );
//                    // 是否读取成功
//                    if(list == null || list.isEmpty()){
//                        continue;
//                    }
//                    // 解析数据
//                    MapRecord<String, Object, Object> entries = list.get(0);
//                    Map<Object, Object> value = entries.getValue();
//                    VoucherOrder voucherOrder = BeanUtil
//                            .fillBeanWithMap(value, new VoucherOrder(), true);
//                    // 保存订单信息到数据库
//                    SaveVoucherOrder(voucherOrder);
//                    // 确认订单信息，将数据从待处理队列中删除
//                    stringRedisTemplate.opsForStream().acknowledge(queueName,"g1",entries.getId());
//                } catch (Exception e) {
//                    log.error("处理订单异常");
//                    while (true){
//                        try {
//                            // 从待处理队列中读取信息
//                            List<MapRecord<String, Object, Object>> list = stringRedisTemplate.opsForStream().read(
//                                    Consumer.from("g1", "c1"),
//                                    StreamReadOptions.empty().count(1),
//                                    StreamOffset.create(queueName, ReadOffset.from("0"))
//                            );
//                            // 是否存在待处理数据
//                            if(list == null || list.isEmpty()){
//                                // 不存在，则退出
//                                break;
//                            }
//                            // 解析数据
//                            MapRecord<String, Object, Object> entries = list.get(0);
//                            Map<Object, Object> value = entries.getValue();
//                            VoucherOrder voucherOrder = BeanUtil
//                                    .fillBeanWithMap(value, new VoucherOrder(), true);
//                            // 插入数据
//                            SaveVoucherOrder(voucherOrder);
//                            // 确认信息
//                            stringRedisTemplate.opsForStream().acknowledge(queueName,"g1",entries.getId());
//                        } catch (Exception ex) {
//                            continue;
//                        }
//                    }
//                }
//            }
//        }
//    }
//
//    private void SaveVoucherOrder(VoucherOrder voucherOrder) {
//        // 获取锁
//        RLock lock = redissonClient.getLock("lock:order:" + voucherOrder.getUserId());
//        boolean success = lock.tryLock();
//        if(success){
//            try {
//                proxy.getResult(voucherOrder);
//            } finally {
//                lock.unlock();
//            }
//        }
//    }
//
//    /**
//     * 抢购秒杀券
//     * @param voucherId
//     */
//    private IVoucherOrderService proxy;
//    public Result seckillVoucher(Long voucherId) {
//        long orderId = redisIdWorker.nextId("order");
//        Long userId = UserHolder.getUser().getId();
//        // 是否有下单资格
//        // 执行lua脚本
//        Long res = stringRedisTemplate.execute(
//                SECKILL_SCRRPT,
//                Collections.emptyList(),
//                String.valueOf(voucherId), String.valueOf(userId),String.valueOf(orderId)
//        );
//
//        if(res!=0){
//            // 不为0说明下单失败
//            return Result.fail(res == 1 ? "库存不足":"用户已经下过一单了");
//        }
//        // 有下单资格，已存入消息队列
//        proxy = (IVoucherOrderService) AopContext.currentProxy();
//        return Result.ok(orderId);
//    }
//
//
//    /*@Override
//    public Result seckillVoucher(Long voucherId) {
//        // 查询优惠券信息
//        SeckillVoucher seckillVoucher = getById(voucherId);
//        if (seckillVoucher == null) {
//            return Result.fail("优惠券不存在");
//        }
//        // 判断秒杀是否开始
//        if(LocalDateTime.now().isBefore(seckillVoucher.getBeginTime())||
//        LocalDateTime.now().isAfter(seckillVoucher.getEndTime())){
//            return Result.fail("不在优惠券售卖时间内");
//        }
//        // 判断库存是否充足
//        if(seckillVoucher.getStock()<1){
//            return Result.fail("库存不足");
//        }
//
//        Long id = UserHolder.getUser().getId();
//
//        // 获取锁
////        SimpleRedisLock lock = new SimpleRedisLock("order:"+id,stringRedisTemplate);
//        RLock lock = redissonClient.getLock("lock:order:" + id);
//        boolean success = lock.tryLock();
//        if(success){
//            try {
//                ISeckillVoucherService proxy = (ISeckillVoucherService) AopContext.currentProxy();
//                return proxy.getResult(voucherId, seckillVoucher);
//            } finally {
//                lock.unlock();
//            }
//        }
//        return Result.fail("每人限购一单");
//    }*/
//
//    @Transactional
//    public void getResult(VoucherOrder voucherOrder) {
//        // 扣除库存
//        boolean success = iSeckillVoucherService.update()
//                .setSql("stock = stock - 1")
//                .eq("voucher_id",voucherOrder.getVoucherId())
//                .gt("stock",0)
//                .update();
//        if(!success){
//            log.error("库存不足");
//        }
//        // 添加订单信息
//        iVoucherOrderService.save(voucherOrder);
//    }
//}
